﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetfractionHub.LocalMachine.BotCommands;
using NetfractionHub.Network.Protocol;
using NetfractionHub.Network.Protocol.BASE.Factory;

namespace Netfraction.Hub.Bots.AnnouncerBot.Handlers
{
	[CommandHandler("addrelease")]
	public class AddRelease : CommandHandler
	{
		public override bool HandleCommandMessage(NetfractionHub.RemoteMachine.Node source, CommandMessage message)
		{
			string magnet = string.Empty;
			string catName = string.Empty;
			int catId = 0;
			int userId = 0;

			if (CheckArgumentMix(message, 2))
			{
				if (CheckArgumentMix(message, 2, 0, 0))
				{
					if (!SetVariableToStringArgument(message, "magnet", out magnet))
					{
						// missing magnet
						return false;
					}

					if (message.StringArguments.ContainsKey("categoryName"))
					{
						catName = message.StringArguments["categoryName"];
						catId = GetCategoryIdFromName(catName);
						if (catId == 0)
						{
							return false;
						}
					}
					else if (message.StringArguments.ContainsKey("categoryId") && int.TryParse(message.StringArguments["categoryId"], out catId))
					{
						catName = GetCategoryNameFromId(catId);
						if (string.IsNullOrEmpty(catName))
						{
							return false;
						}
					}
					else
					{
						// missing category
						return false;
					}
				}
				else if (message.UnnamedArguments.Count == 2)
				{
					if (int.TryParse(message.UnnamedArguments[0], out catId))
					{
						catName = GetCategoryNameFromId(catId);
						if (string.IsNullOrEmpty(catName))
						{
							return false;
						}
					}
					else
					{
						catName = message.UnnamedArguments[0];
						catId = GetCategoryIdFromName(catName);
						if (catId == 0)
						{
							return false;
						}
					}

					magnet = message.UnnamedArguments[1];
				}

				// get userId for username, or add it.
				userId = GetUserIdFromUsername(source.Identity.Nickname);
				if (userId == 0)
				{
					userId = InsertUser(source.Identity.Nickname);
					if (userId == 0)
					{
						return false;
					}
				}

				int retVal = AnnouncerBot.DataStore.ExecuteNonQuery(String.Format(System.Globalization.CultureInfo.InvariantCulture, "INSERT INTO Entries (AddedBy, CategoryId, Magnet) VALUES ({0}, {1}, '{2}')", userId, catId, magnet));
				if (retVal == 1)
				{
					this.ParentBot.SendBroadcastMessageFromBot(String.Format(System.Globalization.CultureInfo.InvariantCulture, "The entry {0} has been added to the Announcer database, under the category '{1}'.", magnet, catName));
				}
			}
			else if (CheckArgumentMix(message, 1))
			{
				if (!SetVariableToStringArgument(message, "magnet", out magnet))
				{
					if (message.UnnamedArguments.Count == 1)
					{
						magnet = message.UnnamedArguments[0];
					}
					else
					{
						return false;
					}
				}
				int retVal = AnnouncerBot.DataStore.ExecuteNonQuery(String.Format(System.Globalization.CultureInfo.InvariantCulture, "INSERT INTO Entries (AddedBy, Magnet) VALUES ({0}, {1}, '{2}')", userId, magnet));
				if (retVal == 1)
				{
					this.ParentBot.SendBroadcastMessageFromBot(String.Format(System.Globalization.CultureInfo.InvariantCulture, "The entry {0} has been added to the Announcer database.", magnet));
				}
			}
			else
			{
				return false;
			}

			return true;
		}

		private bool CheckArgumentMix(CommandMessage message, int totalArguments)
		{
			return message.ArgumentsCount == totalArguments;
		}

		private bool CheckArgumentMix(CommandMessage message, int stringArguments, int booleanArguments, int unnamedArguments)
		{
			return (message.StringArguments.Count == stringArguments) && (message.BooleanArguments.Count == booleanArguments) && (message.UnnamedArguments.Count == unnamedArguments);
		}

		private bool SetVariableToStringArgument(CommandMessage message, string argumentKey, out string value)
		{
			value = string.Empty;
			if (!message.StringArguments.ContainsKey(argumentKey))
			{
				return false;
			}
			value = message.StringArguments[argumentKey];
			return true;
		}

		private int GetUserIdFromUsername(string name)
		{
			object tempVal = AnnouncerBot.DataStore.ExecuteScalar(String.Format(System.Globalization.CultureInfo.InvariantCulture, "SELECT UserId FROM Users WHERE Username='{0}'", name));
			if (tempVal != null && (tempVal is Int64 || tempVal is Int32))
			{

				return tempVal is Int64 ? CastInt64ToInt((Int64)tempVal) : (int)tempVal;
			}
			else
			{
				return 0;
			}
		}

		private int CastInt64ToInt(Int64 num)
		{
			if (num > int.MinValue && num < int.MaxValue)
			{
				return Convert.ToInt32(num);
			}
			else
			{
				return 0;
			}
		}

		private int InsertUser(string name)
		{
			int retVal = AnnouncerBot.DataStore.ExecuteNonQuery(String.Format(System.Globalization.CultureInfo.InvariantCulture, "INSERT INTO Users (Username) VALUES ('{0}')", name));
			if (retVal == 1)
			{
				return GetUserIdFromUsername(name);
			}
			return 0;
		}

		private int GetCategoryIdFromName(string name)
		{
			object tempVal = AnnouncerBot.DataStore.ExecuteScalar(String.Format(System.Globalization.CultureInfo.InvariantCulture, "SELECT CategoryId FROM Categories WHERE Name='{0}'", name));
			if (tempVal != null && (tempVal is Int64 || tempVal is Int32))
			{
				return tempVal is Int64 ? CastInt64ToInt((Int64)tempVal) : (int)tempVal;
			}
			else
			{
				return 0;
			}
		}

		private string GetCategoryNameFromId(int id)
		{
			object tempVal = AnnouncerBot.DataStore.ExecuteScalar(String.Format(System.Globalization.CultureInfo.InvariantCulture, "SELECT Name FROM Categories WHERE CategoryId='{0}'", id));
			if (tempVal != null && tempVal is string)
			{
				return tempVal.ToString();
			}
			else
			{
				return string.Empty;
			}
		}
	}
}
